﻿#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <string.h>


int main()
{
//************************************************************
// 1、一维数组a（sizeof）
 	
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));  
	//解析：int类型元素大小是4，
	//因为组数名a单独sizeof里面，所以这里表示整个数组的大小，
	//所以大小是16；

	printf("%d\n", sizeof(a + 0));
	//解析：a并没有单独放在sizeof中，也没有&a，
	//所以（a+0）代表首元素的地址，
	//大小是4\8;

	printf("%d\n", sizeof(*a));
	//解析：因为*解引用a，a代表首元素地址，也就是1，
	//大小是4；
	
	printf("%d\n", sizeof(a + 1));
	//解析：与（a+0）一样，代表着第二个字符地址，
	//大小是4\8；
	
	printf("%d\n", sizeof(a[1]));
	//解析：一维数组的数组名[下标]代表第几个元素，
	//a[1]代表了第二个元素，
	//大小是4；

	printf("%d\n", sizeof(&a));
	//解析：&a表示取出整个数组的地址，
	// 数组地址也是地址，不会*元素个数，
	//大小是4\8
	
	printf("%d\n", sizeof(*&a));
	//解析：取数组地址后解引用，解的是整个数组，
	//大小是16；
	
	printf("%d\n", sizeof(&a + 1));
	//解析：取数组地址后+1，就是加上一个数组大小的地址，
	//大小是4\8；
	
	printf("%d\n", sizeof(&a[0]));
	//解析：取出，也就是首元素地址，也是地址，
	//大小是4\8
	
	printf("%d\n", sizeof(&a[0] + 1));
	//解析：取出a[0]+1的地址，就是首元素后面的地址，第二个元素地址，
	//大小是4\8

//************************************************************
// 2、字符数组arr（sizeof）

	//字符数组
	//char arr[] = { 'a','b','c','d','e','f' };
	//printf("%d\n", sizeof(arr));
	////解析：arr单独放在sizeof中，表示整个数组的大小，
	////char类型一个元素大小是1，
	////大小是6；

	//printf("%d\n", sizeof(arr + 0));
	////解析：arr没有单独存放，arr+0表示a的地址，
	////大小是4\8；

	//printf("%d\n", sizeof(*arr));
	////解析：arr没有单独存放，表示解引用首元素大小，
	//// 大小是1；
	//
	//printf("%d\n", sizeof(arr[1]));
	////解析：表示一维数组中下标为1的元素，也就是'b',
	////大小是1；

	//printf("%d\n", sizeof(&arr));
	////解析：取出整个arr数组的地址，
	////大小是4\8；

	//printf("%d\n", sizeof(&arr + 1));
	////解析：指向arr的地址的指针，向后移动一个数组大小，
	////仍是指针
	////大小是4\8；

	//printf("%d\n", sizeof(&arr[0] + 1));
	////解析：取出arr数组下标为[0]的元素地址，向后一个单位，仍是指针，
	////大小是4\8；
	
//************************************************************
// 3、字符串数组arr（strlen）

	//char arr[] = { 'a','b','c','d','e','f' };
	//printf("%d\n", strlen(arr));
	////解析：因为此arr数组内没有标明'\0'，所以一直执行到'\0'结束，
	////大小是随机值；

	//printf("%d\n", strlen(arr + 0));
	////解析：由于arr不是单独在内，所以arr+0是首元素地址，
	////也就是从首元素开始执行，
	////大小是随机值；
	//
	//printf("%d\n", strlen(*arr));
	////解析：由于arr不是单独在内，所以arr是首元素地址，
	////解引用首元素地址，找到'a'，
	////由于比较的是ASCLL值，所以无法比较，
	////大小是 报错；

	//printf("%d\n", strlen(arr[1]));
	////解析：找到下标为[1]的元素，是'b'，
	////ASCLL值无法比较，
	////大小是 报错；

	//printf("%d\n", strlen(&arr));
	////解析：取地址arr整个数组，
	////大小是随机值；

	//printf("%d\n", strlen(&arr + 1));
	////解析：取出整个数组的地址，往后加上一个数组指针大小，
	////也就是指针到'f'的后面，比&arr更快找到'\0'，
	////大小是随机值-6；

	//printf("%d\n", strlen(&arr[0] + 1));
	////解析：取出首元素地址，往后一个char类型指针单位，
	////也就是指向'b'，
	////大小是随机值-1；
	
//************************************************************
// 4、字符串数组arr（sizeof）

	//char arr[] = "abcdef";
	//printf("%d\n", sizeof(arr));
	////解析：在sizeof中单独存放，表示整个数组，
	////由于"abcdef"中包含了'\0',
	////所以有7个元素，
	////大小是7；

	//printf("%d\n", sizeof(arr + 0));
	////解析，无单独存放，表示首元素地址，
	////大小是4\8；
	//
	//printf("%d\n", sizeof(*arr));
	////解析：无单独存放，表示首元素地址，解引用找到'a'，
	////大小是1；

	//printf("%d\n", sizeof(arr[1]));
	////解析：找到下标为[1]的元素，是'a'，
	////大小是1；

	//printf("%d\n", sizeof(&arr));
	////解析：取出整个数组的地址，仍是地址，
	////大小是4\8；

	//printf("%d\n", sizeof(&arr + 1));
	////解析：取出整个数组地址，
	////加上一个指针类型是char(*)[]类型的指针，指向arr[7],
	////大小是4\8；

	//printf("%d\n", sizeof(&arr[0] + 1));
	////解析：找到首元素地址，加上一个指针类型是char*的指针，指向arr[1]，
	////大小是4\8；

//************************************************************
// 5、字符串数组arr（strlen）

 //   char arr[] = "abcdef";
	//printf("%d\n", strlen(arr));
	////解析："abcdef"中包含了'\0'，
	////大小为6；

	//printf("%d\n", strlen(arr + 0));
	////解析：由于没有单独存放，arr表示首元素地址，
	////从首元素开始执行，
	////大小为6；

	//printf("%d\n", strlen(*arr));
	////解析：没有单独存放，解引用首元素地址，
	////ASCLL值无法比较，
	////大小为 报错；

	//printf("%d\n", strlen(arr[1]));
	////解析：找到下标为[1]的元素，
	////ASCLL值无法比较，
	////大小为报错；

	//printf("%d\n", strlen(&arr));
	////解析：取出整个数组的地址，
	////大小为6；
	//
	//printf("%d\n", strlen(&arr + 1));
	////解析：加一个指针类型为数组指针的指针大小，指向arr[7]，
	////大小为随机值；

	//printf("%d\n", strlen(&arr[0] + 1));
	////解析：加上一个指针类型为char*类型的指针大小，指向arr[1]，
	////大小为5；

//************************************************************
// 6、字符串指针p（sizeof）

	//char* p = "abcdef";
	//printf("%d\n", sizeof(p));
	////解析：p是字符串首元素的地址，
	////大小为4\8；
	//
	//printf("%d\n", sizeof(p + 1));
	////解析：p+1是首元素+1,就是'b'的地址，
	////大小为4\8；
	//
	//printf("%d\n", sizeof(*p));
	////解析：解引用地址p，得到数组首字母，
	////大小为1；
	//
	//printf("%d\n", sizeof(p[0]));
	////解析：字符串地址首元素，p[0]==*(p+0),
	////大小为1；

	//printf("%d\n", sizeof(&p));
	////解析：取出存放指针p的地址，也是地址，
	////大小为4\8；
	//
	//printf("%d\n", sizeof(&p + 1));
	////解析：取出存放指针p的地址，加上一个&p大小的指针，也是地址，
	////大小为4\8；
	//
	//printf("%d\n", sizeof(&p[0] + 1));
	////解析：&p[0]就是第一个元素取地址，加一就第二个元素，也是地址，
	////大小为4\8；
	//
//************************************************************
// 7、字符串指针p（strlen）

	//char* p = "abcdef";
	//printf("%d\n", strlen(p));
	////解析：字符串包含'\0'，
	////大小为6；
	//
	//printf("%d\n", strlen(p + 1));
	////解析：p为首元素地址，p+1就是第二个元素，
	////大小为5；
	//
	//printf("%d\n", strlen(*p));
	////解析：解引用首元素地址，就是'a'，
	////ASCLL值无法比较，
	////大小是 报错；
	//
	//printf("%d\n", strlen(p[0]));
	////解析：p[0]就是首元素，就是'a'，
	////ASCLL值，
	////大小是 报错；
	//
	//printf("%d\n", strlen(&p));
	////解析：取出p的地址，p的后面是未知数，
	////大小是随机值；
	//
	//printf("%d\n", strlen(&p + 1));
	////解析：&p+1就是加上一个p大小的指针，指向&p后面未知数，
	////大小是随机值；

	//printf("%d\n", strlen(&p[0] + 1));
	////解析：p先和[]反应，&p[0]就是取出首元素地址，
	////加一就是第二个元素地址，
	////大小是5；

//************************************************************
// 8、二维数组（sizeof）
	
	//int a[3][4] = { 0 };
	//printf("%d\n", sizeof(a));
	////解析：由于a单独存放在sizeof()中，所以表示整个二维数组大小，
	////一个int类型大小是4，有3行4元素，3*4*4
	////大小是48；

	//printf("%d\n", sizeof(a[0][0]));
	////解析：a[0][0]表示首行首元素，就是0，
	////大小为4；
	//
	//printf("%d\n", sizeof(a[0]));
	////解析：a是二位数组，可以把a看作有3个一维数组，
	////a[0]可以理解为a第一个一维数组的数组名，访问里面0-3的元素，
	////大小为16；

	//printf("%d\n", sizeof(a[0] + 1));
	////解析：a[0]没有单独放在sizeof中，也没有&，
	////所以a[0]表示首元素地址，a[0]+1就是首行第二个元素地址
	////大小为4\8；
	//
	//printf("%d\n", sizeof(*(a[0] + 1)));
	////解析：首行第二个元素解引用，
	////大小为4；
	//
	//printf("%d\n", sizeof(a + 1));
	////解析：a没有单独放在sizeof中，所以代表首元素地址，
	////也就是第一行的地址，a+1表示第二行地址；
	////大小为4\8;
	//
	//printf("%d\n", sizeof(*(a + 1)));
	////解析：解引用a[1];
	////大小为16；
	//
	//printf("%d\n", sizeof(&a[0] + 1));
	////解析：由于&a[0]取出a首行元素地址,&a[0]+1表示下一行的地址，
	////大小为4\8；

	//printf("%d\n", sizeof(*(&a[0] + 1)));
	////解析：解引用第二行地址，访问4个元素，
	////大小为16；

	//printf("%d\n", sizeof(*a));
	////解析：a没有单独存放，也没有&，所以表示首元素地址，也就是a[0]的地址，
	////解引用a[0]，访问4个元素，
	////大小为16；

	//printf("%d\n", sizeof(a[3]));
	////解析：由于sizeof函数是不会计算的，打个比方：如果知道返回的数值是int类型，
	////那就会直接返回sizeof(int)，不会计算其中的内容，
	////所以就算是不存在也依旧是根据类型判断，当它是a[3][4],a[-1]也是如此。
	////大小为16；

	return 0;
}


